signature ENV =
sig
    type ty

    datatype enventry = VarEntry of { access : Translate.access, ty : ty }
		      | FunEntry of { level : Translate.level, label : Temp.label, formals : ty list, result : ty }

    type tenv = ty Symbol.table
    type venv = enventry Symbol.table

    val base_tenv : tenv
    val base_venv : venv
end

structure Env : ENV =
struct
    structure M = Temp
    structure S = Symbol
    structure T = Types
    structure X = Translate

    type ty = T.ty

    datatype enventry = VarEntry of { access : X.access, ty : ty }
		      | FunEntry of { level : X.level, label : M.label, formals : ty list, result : ty }

    type tenv = ty Symbol.table
    type venv = enventry Symbol.table

    val base_venv = foldl (fn ((name, formals, result), venv) => S.enter (venv, S.symbol name, FunEntry{level = X.outermost,
													label = M.namedlabel name,
													formals = formals,
													result = result}))
			  S.empty
			  [("print",     [T.STRING],               T.UNIT),
			   ("flush",     [],                       T.UNIT),
			   ("getchar",   [],                       T.STRING),
			   ("ord",       [T.STRING],               T.INT),
			   ("chr",       [T.INT],                  T.STRING),
			   ("size",      [T.STRING],               T.INT),
			   ("substring", [T.STRING, T.INT, T.INT], T.STRING),
			   ("concat",    [T.STRING, T.STRING],     T.STRING),
			   ("not",       [T.INT],                  T.INT),
			   ("exit",      [T.INT],                  T.UNIT)]
		    
    val base_tenv = foldl (fn ((name, ty), tenv) => S.enter (tenv, S.symbol name, ty))
			  S.empty
			  [("int",    T.INT),
			   ("string", T.STRING),
			   ("unit", T.UNIT)]
end
